package brc.syntacticTree;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Writer;
import java.util.List;

public class ProgramNode implements TreeNode {
	/**
	 * 
	 */
	private static final long serialVersionUID = -659968921647358703L;
	private List<FunctionNode> functions;
	
	public ProgramNode(List<FunctionNode> functions) {
		if (functions == null) {
			throw new NullPointerException();
		}
		this.functions = functions;
	}
	
	public List<FunctionNode> getFunctions() {
		return functions;
	}

	@Override
	public void writeAssembly(Writer writer) throws IOException {
		writer.write(";Cabecalho padrao do assembly\r\n");
		writer.write(".source BrC.java\r\n");
		writer.write(".class public BrC\r\n");
		writer.write(".super java/lang/Object\r\n");
		writer.write(".method public <init>()V\r\n");
		writer.write(".limit stack 1\r\n");
		writer.write(".limit locals 1\r\n");
		writer.write("aload_0\r\n");
		writer.write("invokespecial java/lang/Object/<init>()V\r\n");
		writer.write("return\r\n");
		writer.write(".end method\r\n");
		writer.write(".method public static main([Ljava/lang/String;)V \r\n");
		writer.write(".limit stack 32\r\n");
		writer.write(".limit locals 40\r\n");
		
		for (FunctionNode func : this.functions) {
			func.writeAssembly(writer);
		}
		
		writer.write("return\r\n");
		writer.write(".end method\r\n");
	}

	@Override
	public void semanticCheck() throws SemanticException {
		for (FunctionNode func : this.functions) {
			try {
				func.semanticCheck();
			} catch (SemanticException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
	
	public void saveAs(String file) throws IOException {
		if (file == null || file.isEmpty()) {
			throw new NullPointerException();
		}
		FileOutputStream stream = new FileOutputStream(file);

		ObjectOutputStream buffer = new ObjectOutputStream(stream);
		buffer.writeObject(this);
		
		stream.close();
	}

	public static ProgramNode open(String file) throws IOException {
		if (file == null || file.isEmpty()) {
			throw new NullPointerException();
		}
		
		FileInputStream stream = new FileInputStream(file);
        ObjectInputStream buffer = new ObjectInputStream(stream);

        try {
			return (ProgramNode)buffer.readObject();
		} catch (ClassNotFoundException e) {
			return null;
		}
		finally {
			stream.close();
		}
	}
}
